gdk: Add opaque region setters
authorJasper St. Pierre <jstpierre@mecheye.net>
Tue, 14 May 2013 20:23:33 +0000 (16:23 -0400)
committerJasper St. Pierre <jstpierre@mecheye.net>
Wed, 28 Aug 2013 14:33:57 +0000 (10:33 -0400)
https://bugzilla.gnome.org/show_bug.cgi?id=706922

gdk/gdkwindow.c
gdk/gdkwindow.h
gdk/gdkwindowimpl.h
gdk/wayland/gdkwindow-wayland.c
gdk/x11/gdkwindow-x11.c

index cf5d75113fcc097d2eab6379666924c46410f8a0..55f5bf285520719a9c5b1a8b1501dffdb13eb77c 100644 (file)
@@ -10787,3 +10787,39 @@ gdk_window_get_scale_factor (GdkWindow *window)
 
   return 1;
 }
+
+/**
+ * gdk_window_set_opaque_region:
+ * @window: a top-level or non-native #GdkWindow
+ * @region: a region
+ *
+ * For optimizization purposes, compositing window managers may
+ * like to not draw obscured regions of windows, or turn off blending
+ * during for these regions. With RGB windows with no transparency,
+ * this is just the shape of the window, but with ARGB32 windows, the
+ * compositor does not know what regions of the window are transparent
+ * or not.
+ *
+ * This function only works for toplevel windows.
+ *
+ * GTK+ will automatically update this property automatically if
+ * the @window background is opaque, as we know where the opaque regions
+ * are. If your window background is not opaque, please update this
+ * property in your #GtkWindow::style_updated handler.
+ *
+ * Since: 3.10
+ */
+void
+gdk_window_set_opaque_region (GdkWindow      *window,
+                              cairo_region_t *region)
+{
+  GdkWindowImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (!GDK_WINDOW_DESTROYED (window));
+
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->set_opaque_region)
+    return impl_class->set_opaque_region (window, region);
+}
index eff71783ccb06c2104d8d567ab2c97baa48e1793..de7872e4bb7cdef325dc99211cb75cbb3ea0e0b4 100644 (file)
@@ -1086,6 +1086,10 @@ gboolean   gdk_window_get_support_multidevice (GdkWindow *window);
 GDK_AVAILABLE_IN_3_8
 GdkFrameClock* gdk_window_get_frame_clock      (GdkWindow     *window);
 
+GDK_AVAILABLE_IN_3_10
+void       gdk_window_set_opaque_region        (GdkWindow      *window,
+                                                cairo_region_t *region);
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_H__ */
index 97ac21ce07f80cbb0aa663676c50abc999f36c68..b0b43b9105581d515f9c5ffa2242278fd4c7d830 100644 (file)
@@ -292,6 +292,9 @@ struct _GdkWindowImplClass
                                            GdkAtom         property);
 
   gint         (* get_scale_factor)       (GdkWindow      *window);
+
+  void         (* set_opaque_region)      (GdkWindow      *window,
+                                           cairo_region_t *region);
 };
 
 /* Interface Functions */
index acb29e3f7f930e30c820c5ea3ac5404063bd80ea..d2d0b644f5d07e6f15ef5107f5a3769873263597 100644 (file)
@@ -2020,6 +2020,46 @@ gdk_wayland_window_get_scale_factor (GdkWindow *window)
   return impl->scale;
 }
 
+static struct wl_region *
+wl_region_from_cairo_region (GdkWaylandDisplay *display,
+                             cairo_region_t    *region)
+{
+  struct wl_region *wl_region;
+  int i, n_rects;
+
+  wl_region = wl_compositor_create_region (display->compositor);
+  if (wl_region == NULL)
+    return NULL;
+
+  n_rects = cairo_region_num_rectangles (region);
+  for (i = 0; i < n_rects; i++)
+    {
+      cairo_rectangle_int_t rect;
+      cairo_region_get_rectangle (region, i, &rect);
+      wl_region_add (wl_region, rect.x, rect.y, rect.width, rect.height);
+    }
+
+  return wl_region;
+}
+
+static void
+gdk_wayland_window_set_opaque_region (GdkWindow      *window,
+                                      cairo_region_t *region)
+{
+  GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  struct wl_region *wl_region;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)), region);
+  if (wl_region == NULL)
+    return;
+
+  wl_surface_set_opaque_region (impl->surface, wl_region);
+  wl_region_destroy (wl_region);
+}
+
 
 static void
 _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
@@ -2109,6 +2149,7 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
   impl_class->change_property = gdk_wayland_window_change_property;
   impl_class->delete_property = gdk_wayland_window_delete_property;
   impl_class->get_scale_factor = gdk_wayland_window_get_scale_factor;
+  impl_class->set_opaque_region = gdk_wayland_window_set_opaque_region;
 }
 
 
index cff720eeed7bd4c6cc915f2ce67f93bc983bfb05..a88cf8e242169c6ae8d3ec7fde4f892885570542 100644 (file)
@@ -5555,6 +5555,51 @@ gdk_x11_window_set_frame_sync_enabled (GdkWindow *window,
   GDK_WINDOW_IMPL_X11 (window->impl)->frame_sync_enabled = FALSE;
 }
 
+static void
+gdk_x11_window_set_opaque_region (GdkWindow      *window,
+                                  cairo_region_t *region)
+{
+  GdkDisplay *display;
+
+  int nitems;
+  gulong *data;
+
+  if (region != NULL)
+    {
+      int i, nrects;
+
+      nrects = cairo_region_num_rectangles (region);
+      nitems = nrects * 4;
+      data = g_new (gulong, nitems);
+
+      for (i = 0; i < nrects; i++)
+        {
+          cairo_rectangle_int_t rect;
+          cairo_region_get_rectangle (region, i, &rect);
+          data[i+0] = rect.x;
+          data[i+1] = rect.y;
+          data[i+2] = rect.width;
+          data[i+3] = rect.height;
+        }
+    }
+  else
+    {
+      nitems = 0;
+      data = NULL;
+    }
+
+  display = gdk_window_get_display (window);
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                   GDK_WINDOW_XID (window),
+                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_OPAQUE_REGION"),
+                   XA_CARDINAL, 32, PropModeReplace,
+                   (guchar *) data, nitems);
+
+  if (data != NULL)
+    g_free (data);
+}
+
 static void
 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
 {
@@ -5643,4 +5688,5 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
   impl_class->change_property = _gdk_x11_window_change_property;
   impl_class->delete_property = _gdk_x11_window_delete_property;
   impl_class->get_scale_factor = gdk_x11_window_get_scale_factor;
+  impl_class->set_opaque_region = gdk_x11_window_set_opaque_region;
 }